package org.jflame.commons.crypto;

public record DelegateEncryptor(BaseEncryptor encryptor, CipherArgs algArgs) {

    /**
     * 构造函数
     *
     * @param encryptor 加解密实现类
     * @param algArgs 加解密需要用到的参数,如果密钥,向量等
     */
    public DelegateEncryptor {
    }

    /**
     * 加密
     *
     * @param plaintext 待加密字符串
     * @return 密文, 默认base64编码
     * @throws EncryptException
     */
    public String encrypt(String plaintext) throws EncryptException {
        return encryptor.encrypt(plaintext, algArgs);
    }

    /**
     * 加密
     *
     * @param rawData 待加密内容
     * @return
     * @throws EncryptException
     */
    public byte[] encrypt(byte[] rawData) throws EncryptException {
        return encryptor.encrypt(rawData, algArgs);
    }

    /**
     * 解密
     *
     * @param cipherText 密文
     * @return 明文
     * @throws EncryptException
     */
    public String decrypt(String cipherText) throws EncryptException {
        return encryptor.decrypt(cipherText, algArgs);
    }

    /**
     * 解密
     *
     * @param cipherData 密文
     * @return
     * @throws EncryptException
     */
    public byte[] decrypt(byte[] cipherData) throws EncryptException {
        return encryptor.decrypt(cipherData, algArgs);
    }

    public Transformation getTransformation() {
        return encryptor.getTransformation();
    }

    /**
     * 构造AES加解密类实例, 模式:AES/ECB/PKCS5PADDING
     *
     * @param secretKey 密钥
     * @return
     */
    public static DelegateEncryptor AES(String secretKey) {
        try {
            SymmetricEncryptor encryptor = new SymmetricEncryptor(Transformation.AES_ECB_PKCS5PADDING);
            return new DelegateEncryptor(encryptor, encryptor.buildArgs(secretKey));
        } catch (EncryptException e) {
            // 不会发生
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 构造AES加解密类实例, 模式:AES/CBC/PKCS5PADDING
     *
     * @param secretKey 密钥
     * @param iv 向量
     * @return
     */
    public static DelegateEncryptor AES(byte[] secretKey, byte[] iv) {
        try {
            SymmetricEncryptor encryptor = new SymmetricEncryptor(Transformation.AES_CBC_PKCS5PADDING);
            return new DelegateEncryptor(encryptor, encryptor.buildArgs(secretKey, iv));
        } catch (EncryptException e) {
            // 不会发生
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 构造PBEWithMD5AndDES加解密实例类
     *
     * @param password 用户口令
     * @param salt 盐
     * @param iterationCount 迭代次数
     * @return
     */
    public static DelegateEncryptor PBE(String password, byte[] salt, int iterationCount) {
        try {
            SymmetricEncryptor encryptor = SymmetricEncryptor.of(Alg.PBEWithMD5AndDES, null, null);
            CipherArgs args = encryptor.buildArgs(password)
                    .PBEInitParam(salt, iterationCount);
            return new DelegateEncryptor(encryptor, args);
        } catch (EncryptException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 构造PBE_HMACSHA_AES_256加解密实例类
     *
     * @param password 用户口令
     * @param salt 盐
     * @param iterationCount 迭代次数
     * @param iv 向量,由于使用aes/cbc/pad5需要向量
     * @return
     * @throws EncryptException
     */
    public static DelegateEncryptor PBES2(String password, byte[] salt, int iterationCount, byte[] iv)
            throws EncryptException {
        SymmetricEncryptor encryptor = new SymmetricEncryptor(Transformation.PBE_HMACSHA_AES_256);
        CipherArgs args = encryptor.buildArgs(password)
                .PBEInitParam(salt, iterationCount, iv);
        return new DelegateEncryptor(encryptor, args);
    }

    /**
     * 构造RSA_ECB_PKCS1PADDING加解密实例类
     *
     * @return
     * @throws EncryptException
     */
    public static DelegateEncryptor RSA(String publicKey, String privateKey) {
        try {
            RSAEncryptor rsa = new RSAEncryptor();
            return new DelegateEncryptor(rsa, rsa.buildArgs(publicKey, publicKey));
        } catch (EncryptException e) {
            // 不会发生
            e.printStackTrace();
            return null;
        }
    }

}
